package com.ygqh.baby.controller.os;

import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.util.JSONPObject;
import com.ygqh.baby.ao.AppType;
import com.ygqh.baby.ao.DataStatus;
import com.ygqh.baby.ao.Message;
import com.ygqh.baby.po.YgUser;
import com.ygqh.baby.po.YgUserBalance;
import com.ygqh.baby.service.YgCardCouponDetailService;
import com.ygqh.baby.service.YgUserBalanceService;
import com.ygqh.baby.service.YgUserService;
import com.ygqh.baby.utils.AesCbcUtil;
import com.ygqh.baby.utils.HttpUtil;
import com.ygqh.baby.utils.YgStringUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Controller
@RequestMapping("/mobile/small")
public class AppLoginController {
    @Autowired
    private YgUserService ygUserService;
    @Autowired
    private YgUserBalanceService ygUserBalanceService;
    private Logger logger = Logger.getLogger(AppLoginController.class);
    @Value("${wxsp.appid}")
    private String wxspAppid;
    @Value("${wxsp.secret}")
    private String wxspSecret;

    @Value("${default.head.url}")
    private String defaultHeadUrl;
    @Value("${default.nickName.prefix}")
    private String defaultNickNamePrefix;
    @Autowired
    private YgCardCouponDetailService ygCardCouponDetailService;

    /**
     * 解密用户敏感数据
     *
     * @param encryptedData 明文,加密数据
     * @param iv            加密算法的初始向量
     * @param code          用户允许登录后，回调内容会带上 code（有效期五分钟），开发者需要将 code 发送到开发者服务器后台，使用code 换取
     *                      session_key api，将 code 换成 openid 和 session_key
     * @return
     * @throws Exception
     */
    @ResponseBody
    @RequestMapping(value = "/loginByAuth")
    public JSONPObject loginByAuth(String encryptedData, String iv, @RequestParam(required = true) String code, String fromCode, String callback) {

        Map<String, Object> map = new HashMap<String, Object>();

        // 登录凭证不能为空
        if (code == null || code.length() == 0) {
            map.put("status", 0);
            map.put("msg", "code 不能为空");
            return new JSONPObject(callback, Message.error(map));
        }


        // ////////////// 2、对encryptedData加密数据进行AES解密 ////////////////
        Map<String, String> userInfo = new HashMap<String, String>();

        try {
            JSONObject userInfoJSON = this.getWxUserInfo(wxspAppid, wxspSecret, encryptedData, iv, code);
            if (userInfoJSON != null) {

                String unionId = (String) userInfoJSON.get("unionId");
                String openid = (String) userInfoJSON.get("openId");
                userInfo.put("openId", (String) userInfoJSON.get("openId"));
                userInfo.put("unionId", (String) userInfoJSON.get("unionId"));
                // userInfo.put("unionId", "123456");

                // 根据unionId 判断是否已经存在

                YgUser user = ygUserService.findByUuid(userInfo.get("unionId").toString());

                Boolean isBand = false;
                if (user != null) {
                    // 存在则更新smallOpenId
                    if (StringUtils.isEmpty(user.getSmallOpenId())) {
                        ygUserService.bindingOpenId(user.getId(), null, userInfo.get("openId"), userInfo.get("unionId"));
                    }
                    userInfo.put("isNewCustomer", ygUserService.isNewCustom(user.getId()).toString());
                    if (YgStringUtils.isPhoneLegal(user.getUserName())) {
                        map.put("isBand", true);
                    }
                } else {
                    String headUrl = userInfoJSON.get("avatarUrl").toString();
                    String nickName = userInfoJSON.get("nickName").toString();
                    this.register(openid, unionId, nickName, headUrl, fromCode, AppType.Small);

                    userInfo.put("isNewCustomer", "true");
                    map.put("userInfo", userInfo);
                    return new JSONPObject(callback, Message.success(map));
                }

                UsernamePasswordToken token = new UsernamePasswordToken(user.getUserName(), user.getPassword());
                Subject subject = SecurityUtils.getSubject();
                subject.login(token);

                userInfo.put("userName", user.getUserName());
                userInfo.put("sessionId", subject.getSession().getId().toString());
                userInfo.put("userId", user.getId().toString());
                userInfo.put("nickName", user.getNickName());
                userInfo.put("headImageUrl", user.getHeadImageUrl());
                userInfo.put("isVip", user.getLevel() == 10 ? Boolean.TRUE.toString() : Boolean.FALSE.toString());
                userInfo.put("sourceCodeEncrypt", user.getSourceCodeEncrypt());
                map.put("userInfo", userInfo);
                map.put("isBand", isBand);
                return new JSONPObject(callback, Message.success(map));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new JSONPObject(callback, Message.success(map));
    }

    private JSONObject getWxUserInfo(String appId, String secret, String encryptedData, String iv, String code) throws Exception {
        // 登录凭证不能为空

        // 授权（必填）
        String grant_type = "authorization_code";
        // ////////////// 1、向微信服务器 使用登录凭证 code 获取 session_key 和 openid
        // ////////////////
        // 请求参数
        String params = "appid=" + appId + "&secret=" + secret + "&js_code=" + code + "&grant_type=" + grant_type;
        // 发送请求
        String res = HttpUtil.get("https://api.weixin.qq.com/sns/jscode2session?" + params);
        // 解析相应内容（转换成json对象）
        JSONObject json = JSONObject.parseObject(res);
        // 获取会话密钥（session_key）
        String session_key = json.get("session_key").toString();

        String result = AesCbcUtil.decrypt(encryptedData, session_key, iv, "UTF-8");
        if (!StringUtils.isEmpty(result)) {
            return JSONObject.parseObject(result);
        }
        return null;
    }

    private YgUser register(String openid, String unionId, String nickName, String headUrl, String fromCode, AppType small) {

        Date now = new Date();
        // 注册
        YgUser user = new YgUser();
        user.setUserName(openid);
        user.setPassword("123456a");
        user.setTelPhone("");
        user.setNickName(nickName);
        user.setHeadImageUrl(headUrl);
        user.setUuid(unionId);
        user.setSmallOpenId(openid);
        user.setStatus(DataStatus.Valid);
        user.setCreateTime(now);
        user.setSourceCode(user.getUserName());
        user.setFromCode(fromCode);
        user.setAppType(small);
        ygUserService.save(user);

        YgUserBalance userBalance = new YgUserBalance();
        userBalance.setBalancePrice(new BigDecimal("0.00"));
        userBalance.setCreateTime(new Date());
        userBalance.setFreezePrice(new BigDecimal("0.00"));
        userBalance.setPreincomePrice(new BigDecimal("0.00"));
        userBalance.setUserId(user.getId());
        userBalance.setWithdrawPrice(new BigDecimal("0.00"));
        ygUserBalanceService.save(userBalance);

        // 注册新用户赠送拉新卡券
        ygCardCouponDetailService.asyncGivePullNewCard(user.getId());

        return user;
    }
}
